import { ArrayType,EPSILON } from "./common";
/**
 * 2*2矩阵
 * @class
 * @author jsbrml
 */
class Mat2 extends ArrayType {
    /**
     * 构造函数。
     * @constructor
     * @example
     * let mat=new Mat2([1,2,3,4]);
     */
    constructor(element = [1, 0, 0, 1]) {
        super(element);
    }
    /**
     * 2阶矩阵的克隆。
     * @method
     * @public
     * @example
     * let mat2=new Mat2();
     * let clone=mat2.clone();
     * @returns {Mat2} Mat2。
     */
    clone() {
        return new Mat2(this);
    }
    /**
     * 2阶矩阵的拷贝。
     * @method
     * @public
     * @example
     * let mat2=new Mat2();
     * let copy=new Mat2();
     * copy.copy(mat2);
     * @returns {Mat2} Mat2。
     */
    copy(a) {
        this[0] = a[0];
        this[1] = a[1];
        this[2] = a[2];
        this[3] = a[3];
        return this;
    }
    /**
     * 2阶矩阵的等式判断。
     * @method
     * @public
     * @example
     * let mat2=new Mat2();
     * let mat22=new Mat2();
     * let isEqual=mat2.equal(mat22);//true
     * @returns {Boolean} 是否相等。
     */
    equal(v) {
        let a0 = this[0],
            a1 = this[1],
            a2 = this[2],
            a3 = this[3];
        let b0 = v[0],
            b1 = v[1],
            b2 = v[2],
            b3 = v[3];
        return (
            Math.abs(a0 - b0) <=
            EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) &&
            Math.abs(a1 - b1) <=
            EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) &&
            Math.abs(a2 - b2) <=
            EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) &&
            Math.abs(a3 - b3) <=
            EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3))
        );
    }
    /**
     * 将矩阵设置为单位矩阵。
     * @method
     * @public
     * @example
     * let mat=new Mat2([3,3,3,3]);
     * mat.identity();//[1,0,0,1]
     * @returns {Mat2} 单位矩阵
     */
    identity() {
        this[0] = 1;
        this[1] = 0;
        this[2] = 0;
        this[3] = 1;
        return this;
    }
    /**
     * 对2阶矩阵进行转置变换。
     * @method
     * @public
     * @example
     * let mat=new Mat2([3,3,1,1]);
     * mat.transpose();//[3,1,3,1]
     * @returns {Mat2} 转置矩阵
     */
    transpose() {
        // If we are transposing ourselves we can skip a few steps but have to cache some values
        let a = this.clone();
        this[0] = a[0];
        this[1] = a[2];
        this[2] = a[1];
        this[3] = a[3];
        a = null;
        return this;
    }
    /**
     * 对2阶矩阵进行逆变换。
     * @method
     * @public
     * @example
     * let mat=new Mat2([3,3,1,1]);
     * mat.invert();
     * @returns {Mat2} 逆矩阵
     */
    invert() {
        let a0 = this[0],
            a1 = this[1],
            a2 = this[2],
            a3 = this[3];
        // Calculate the determinant
        let det = a0 * a3 - a2 * a1;

        if (!det) {
            return null;
        }
        det = 1.0 / det;
        this[0] = a3 * det;
        this[1] = -a1 * det;
        this[2] = -a2 * det;
        this[3] = a0 * det;
        return this;
    }
    /**
     * 计算2阶矩阵的伴随阵。
     * @method
     * @public
     * @example
     * let mat=new Mat2([3,0,1,1]);
     * mat.adjoint();
     * @returns {Mat2} 伴随阵
     */
    adjoint() {
        let a0 = this[0],
            a1 = this[1],
            a2 = this[2],
            a3 = this[3];
        this[0] = a3;
        this[1] = -a1;
        this[2] = -a2;
        this[3] = a0;
        return this;
    }
    /**
     * 计算2阶矩阵的行列式。
     * @method
     * @public
     * @example
     * let mat=new Mat2([3,0,1,1]);
     * mat.determinant();
     * @returns {Number} 返回矩阵det
     */
    determinant() {
        return this[0] * this[3] - this[2] * this[1];
    }
    /**
     * 矩阵乘法
     * @method
     * @public
     * @param {Mat2} v 另外一个Mat2矩阵。
     * @example
     * let a=new Mat2([1,0.5,0.2,1]);
     * let b=new Mat2([1,-0.5,0.2,1]);
     * a.multiply(b);//a变为乘后矩阵。
     * //如果保留a,则可以先克隆后乘。
     * let c=a.clone();
     * c.multiply(b);
     * @returns {Mat2} 返回一个新的矩阵。
     */
    multiply(v) {
        let a0 = this[0],
            a1 = this[1],
            a2 = this[2],
            a3 = this[3];
        let b0 = v[0],
            b1 = v[1],
            b2 = v[2],
            b3 = v[3];
        this[0] = a0 * b0 + a2 * b1;
        this[1] = a1 * b0 + a3 * b1;
        this[2] = a0 * b2 + a2 * b3;
        this[3] = a1 * b2 + a3 * b3;
        return this;
    }
    /**
     * 矩阵左乘法
     * @method
     * @public
     * @param {Mat2} v 另外一个Mat2矩阵。
     * @example
     * let a=new Mat2([1,0.5,0.2,1]);
     * let b=new Mat2([1,-0.5,0.2,1]);
     * a.premultiply(b);//a变为乘后矩阵。
     * //如果保留a,则可以先克隆后乘。
     * let c=a.clone();
     * c.premultiply(b);
     * @returns {Mat2} 返回一个新的矩阵。
     */
    premultiply(b) {
        let a0 = b[0],
            a1 = b[1],
            a2 = b[2],
            a3 = b[3];
        let b0 = this[0],
            b1 = this[1],
            b2 = this[2],
            b3 = this[3];
        this[0] = a0 * b0 + a2 * b1;
        this[1] = a1 * b0 + a3 * b1;
        this[2] = a0 * b2 + a2 * b3;
        this[3] = a1 * b2 + a3 * b3;
        return this;
    }
    /**
     * 矩阵缩放变换
     * @method
     * @public
     * @param {Vec2|Array} v 缩放的2维向量或数组。
     * @example
     * let a=new Mat2([1,0.5,0.2,1]);
     * a.scale([2,2]);
     * //或
     * a.scale(new Vec2(2,2));
     * @returns {Mat2} 返回一个新的矩阵。
     */
    scale(v) {
        this[0] *= v[0];
        this[1] *= v[0];
        this[2] *= v[1];
        this[3] *= v[1];
        return this;
    }
    /**
     * 矩阵旋转变换
     * @method
     * @public
     * @param {Number} rad 旋转的弧度。
     * @example
     * let a=new Mat2([1,0.5,0.2,1]);
     * a.rotate(Math.PI/3);//旋转60°
     * @returns {Mat2} 返回一个新的矩阵。
     */
    rotate(rad) {
        let a0 = this[0],
            a1 = this[1],
            a2 = this[2],
            a3 = this[3];
        let s = Math.sin(rad);
        let c = Math.cos(rad);
        this[0] = a0 * c + a2 * s;
        this[1] = a1 * c + a3 * s;
        this[2] = a0 * -s + a2 * c;
        this[3] = a1 * -s + a3 * c;
        return this;
    }
    /**
     * 构建一个旋转rad弧度的矩阵。
     * @method
     * @public
     * @param {Number} rad 旋转的弧度。
     * @example
     * let a=new Mat2();
     * a.fromRotation(Math.PI/3);//旋转60°
     * @returns {Mat2} 返回一个新的矩阵。
     */
    fromRotation(rad) {
        let s = Math.sin(rad);
        let c = Math.cos(rad);
        this[0] = c;
        this[1] = s;
        this[2] = -s;
        this[3] = c;
        return this;
    }
    /**
     * 构建一个缩放v弧度的矩阵。
     * @method
     * @public
     * @param {Vec2|Array} v 缩放量。
     * @example
     * let a=new Mat2();
     * a.fromScaling([2,0.5]);//
     * //或
     * a.fromScaling(new Vec2([2.0.5]));
     * @returns {Mat2} 返回一个新的矩阵。
     */
    fromScaling(v) {
        this[0] = v[0];
        this[1] = 0;
        this[2] = 0;
        this[3] = v[1];
        return this;
    }
    /**
     * 2阶矩阵转换为字符串。
     * @method
     * @public
     * @example
     * let a=new Mat2();
     * a.toString()//"Mat2(1,0,0,1)"
     * @returns {String} 返回矩阵的字符串形式。
     */
    toString() {
        return `Mat2(${this.join(',')})`
    }
}
export { Mat2 }